package sdk.pay.utils.dynamic;

import android.app.Activity;
import android.content.Context;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import dalvik.system.DexClassLoader;
import sdk.pay.PayWebViewInterface;
import sdk.pay.constant.PayConstant;
import sdk.pay.listener.Pay;
import sdk.pay.listener.PayUtilCallBack;
import sdk.pay.model.PayInfo;
import sdk.pay.utils.PayContextUtil;
import sdk.pay.utils.PayLogUtil;

/**
 * Created by Steven on 2016/9/24 0024.
 */

public class PayDynamicHelper {
    private Context mContext;
    private DexClassLoader mDexClassLoader;
    private Pay mPay;

    private PayDynamicHelper() {
    }

    private static class Holder {
        static final PayDynamicHelper mInstance = new PayDynamicHelper();
    }

    public static PayDynamicHelper getInstance() {
        return Holder.mInstance;
    }

    private void initDynamicDownload(Context context) {
        PayContextUtil.getInstance().setContext(context);
        PayDynamicUtil.getInstance().init(context);
    }

    private void setDexClassLoader() {
        if (null == mContext) {
            mContext = PayContextUtil.getInstance().getContext();
            if (null == mContext) {
                throw new ExceptionInInitializerError("Context must be not null!!!");
            }
        }
        if (null == mDexClassLoader) {
            File optimizedDexOutputPath = new File(mContext.getFilesDir().getAbsolutePath(), PayConstant.PATCH_FILE_NAME);
            File dexOutputDir = mContext.getDir("dex", 0);
            mDexClassLoader = new DexClassLoader(optimizedDexOutputPath.getAbsolutePath(),
                    dexOutputDir.getAbsolutePath(), null, mContext.getClassLoader());
        }
    }

    public PayWebViewInterface getPayWebViewInterface(Activity activity, PayInfo mPayInfo) {
        if (null == mDexClassLoader) {
            initDynamicDownload(activity.getApplicationContext());
            setDexClassLoader();
        }
        PayLogUtil.logThird("PayWebView load");
        Class libClass;
        PayWebViewInterface payWebViewInterface = null;
        try {
            libClass = mDexClassLoader.loadClass("sdk.pay.PayWebView");
            Constructor<PayWebViewInterface> constructor =
                    libClass.getConstructor(new Class[]{Activity.class, PayInfo.class});
            payWebViewInterface = constructor.newInstance(activity, mPayInfo);
        } catch (ClassNotFoundException e) {
            PayLogUtil.logThird("ClassNotFoundException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (InstantiationException e) {
            PayLogUtil.logThird("InstantiationException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            PayLogUtil.logThird("IllegalAccessException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            PayLogUtil.logThird("NoSuchMethodException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            PayLogUtil.logThird("InvocationTargetException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        }
        return payWebViewInterface;
    }

    public PayWebViewInterface getPayWebViewInterface(Activity activity, PayInfo mPayInfo,
                                                      PayUtilCallBack callBack) {
        if (null == mDexClassLoader) {
            initDynamicDownload(activity.getApplicationContext());
            setDexClassLoader();
        }
        PayLogUtil.logThird("PayWebView load");
        Class libClass;
        PayWebViewInterface payWebViewInterface = null;
        try {
            libClass = mDexClassLoader.loadClass("sdk.pay.PayWebView");
            Constructor<PayWebViewInterface> constructor =
                    libClass.getConstructor(new Class[]{Activity.class, PayUtilCallBack.class, PayInfo.class});
            payWebViewInterface = constructor.newInstance(activity, callBack, mPayInfo);
        } catch (ClassNotFoundException e) {
            PayLogUtil.logThird("ClassNotFoundException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (InstantiationException e) {
            PayLogUtil.logThird("InstantiationException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            PayLogUtil.logThird("IllegalAccessException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            PayLogUtil.logThird("NoSuchMethodException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            PayLogUtil.logThird("InvocationTargetException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        }
        return payWebViewInterface;
    }

    public Pay getPayUtilsInterface(Activity activity, String appid, String key,
                                    String vector, String systemName, String code,
                                    PayUtilCallBack callback, boolean payStatusListener) {
        if (null == mDexClassLoader) {
            initDynamicDownload(activity.getApplicationContext());
            setDexClassLoader();
        }
        PayLogUtil.logThird("PayHelperIml");
        Class libClass;
        Pay payUtilsInterface = null;
        try {
            libClass = mDexClassLoader.loadClass("sdk.pay.PayHelperIml");
            Constructor<Pay> constructor = libClass.getConstructor(new Class[]{Activity.class,
                    String.class, String.class, String.class, String.class, String.class,
                    PayUtilCallBack.class, boolean.class});
            payUtilsInterface = constructor.newInstance(activity, appid, key, vector,
                    systemName, code, callback, payStatusListener);
            mPay = payUtilsInterface;
        } catch (ClassNotFoundException e) {
            PayLogUtil.logThird("ClassNotFoundException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (InstantiationException e) {
            PayLogUtil.logThird("InstantiationException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            PayLogUtil.logThird("IllegalAccessException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            PayLogUtil.logThird("NoSuchMethodException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            PayLogUtil.logThird("InvocationTargetException reason " + e.getMessage());
            downloadPatchTips();
            e.printStackTrace();
        }
        return payUtilsInterface;
    }

    public Pay getPay() {
        return mPay;
    }

    private void downloadPatchTips() {
        PayLogUtil.logThird("need download sdk patch!");
    }
}